<?php


namespace App\Services;

use Illuminate\Support\Facades\Redis;
use libphonenumber\PhoneNumberUtil;
use Overtrue\EasySms\EasySms;
use PHPUnit\Util\Exception;

class SmsService
{
    const EXP_TIME = 5 * 60; //redis 缓存有效期
    const TEMPLATE_ID = 'SMS_227262168'; //短信发送模板

    /**
     * 短信发送
     */
    public static function send($mobile)
    {
        try {
            $easySmsInstance = new EasySms(config('easysms'));
            $smsCode = self::getSmsCode();
            $easySmsInstance->send($mobile, [
                'template' => self::TEMPLATE_ID,
                'content' => 'null',
                'data' => [
                    'code' => $smsCode,
                    'expTime' => 5,
                ]
            ]);
            info('手机号：' . $mobile . '，验证码 : ' . $smsCode); //日志记录下
            self::cacheSmsCode($mobile, $smsCode);
        } catch (Exception $exception) {
            ErrorMsgService::write($exception, request()->url());
            return false;
        }

        return true;
    }

    /**
     * 检验验证码合法性
     * @param $mobile
     * @param $smsCode
     * @return bool
     */
    public static function checkSmsCode($mobile, $smsCode)
    {
        if (!$code = Redis::get('smsCacheKey:' . $mobile)) {
            throw new Exception('验证码已失效');
        }
        if ($code != $smsCode) {
            throw new Exception('验证码错误');
        }
        Redis::del('smsCacheKey:' . $mobile); //验证通过删除

        return true;
    }

    /**
     * 生成短信验证码
     */
    public static function getSmsCode()
    {
        return rand(1000, 9999);
    }

    /**
     * 验证码存入缓存
     */
    public static function cacheSmsCode($mobile, $smsCode)
    {
        Redis::setex('smsCacheKey:' . $mobile, self::EXP_TIME, $smsCode);
    }

    /**
     * @param $mobile
     * @return bool
     * 验证手机号是否合法
     * 区号映射关系可以在 PhoneNumberUtil::getInstance() 方法中 点击 CountryCodeToRegionCodeMap::$countryCodeToRegionCodeMap 跳过去
     */
    public static function checkMobile($mobile)
    {
        $phoneUtil = PhoneNumberUtil::getInstance();
        try {
            $cnNumberProto = $phoneUtil->parse($mobile, "CN");
            return $phoneUtil->isValidNumber($cnNumberProto);
        } catch (\libphonenumber\NumberParseException $e) {
            ErrorMsgService::write($e, request()->url());
        }
    }
}
